﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using _MetalSlug.Weapons.Units;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using _MetalSlug.Soldiers.Units;
using Microsoft.Xna.Framework.Input;
using _MetalSlug.MyCharacters.HeroDisplayer;
using _MetalSlug.MyCharacters.CharacterBuilers;
using System.Xml;
using _MetalSlug.Mission;
using _MetalSlug.Mementoes;
using _MetalSlug.MyCharacters.Characters.Guns;

namespace _MetalSlug.MyCharacters.Characters
{
    public abstract class MyCharacter : VisibleGameEntity
    {
        public const float SpeedMove = 3f;
        public const float SpeedCrouch = 2f;

        protected String name;
        public String Name
        {
            get { return name; }
        }

        int heightFloor;
        public int HeightFloor
        {
            get { return heightFloor; }
            set { heightFloor = value; }
        }

        public enum CURRENT_ACTIVITY
        {           
            STAND,
            UP,
            RUN,
            JUMP,
            DIE,
            CROUCH,
            SHOOT
        }

        public enum RESOURCE_FACE
        {
            LEFT,
            RIGHT
        }

        protected List<Bullet> Bullets;

        protected bool isdead;
        public bool Isdead
        {
            get { return isdead; }
            set { isdead = value; }
        }

        protected float currentSpeed;

        public float CurrentSpeed
        {
            get { return currentSpeed; }
            set { currentSpeed = value; }
        }

        protected int _hp;

        public int Hp
        {
            get { return _hp; }
            set
            {
                
                if (Hp > value && value > 0)
                {
                    MyDisplayer.ColorDisplay = Color.Red;
                }
                else
                {
                    MyDisplayer.ColorDisplay = Color.White;
                }

                _hp = value;

                if (Hp <= 0)
                {
                    Activity = CURRENT_ACTIVITY.DIE;
                    MyDisplayer.IsAlive = false;
                }
                else
                {
                    MyDisplayer.IsAlive = true;
                    Isdead = false;
                } 
            }
        }


        protected Displayer myDisplayer;

        public Displayer MyDisplayer
        {
            get { return myDisplayer; }
            set { myDisplayer = value; }
        }


        protected Gun currentGun;
        public Gun CurrentGun
        {
            get { return currentGun; }
            set
            {
                if (CurrentGun != value)
                {
                    MyBuilder.Build(Activity, value.TypeOfGun, MyDisplayer);
                }

                currentGun = value;
            }
        }

        List<Gun> lstGuns;

        RESOURCE_FACE facing;
        public RESOURCE_FACE Facing
        {
          get { return facing; }
          set 
          { 
              facing = value;
              if (Facing == RESOURCE_FACE.LEFT)
              {
                  MyDisplayer.SetFlip(MySprite.FLIPABLE.FLIP);
              }

              if (Facing == RESOURCE_FACE.RIGHT)
              {
                  MyDisplayer.SetFlip(MySprite.FLIPABLE.NOT_FLIP);
              }
          }
        }

        protected Vector2 charDirection;

        public Vector2 CharDirection
        {
            get { return charDirection; }
            set { charDirection = value; }
        }

        protected CURRENT_ACTIVITY activity;

        public CURRENT_ACTIVITY Activity
        {
            get { return activity; }
            set
            {   
                if(Activity != value)
                {
                    MyBuilder.Build(value, CurrentGun.TypeOfGun, MyDisplayer);
                }

                activity = value;
                switch (activity)
                {
                    case CURRENT_ACTIVITY.STAND:
                        CurrentSpeed = SpeedMove;
                        break;

                    case CURRENT_ACTIVITY.CROUCH:
                        CurrentSpeed = SpeedCrouch;
                        break;

                    case CURRENT_ACTIVITY.DIE:
                        SetTopLeft(new Vector2(TopLeft.X, HeightFloor));
                        break;
                }

                
            }
        }

        protected int deltaJump;

        public int DeltaJump
        {
            get { return deltaJump; }
            set { deltaJump = value; }
        }

        protected Builder myBuilder;

        public Builder MyBuilder
        {
            get { return myBuilder; }
            set { myBuilder = value; }
        }

        public virtual void InitialAttribute(Vector2 _TopLeft, Vector2 _Size)
        {
            lstGuns = new List<Gun>();
            MyDisplayer = MyBuilder.BuildDefault(_Size);
            Size = MyDisplayer.Size;
            Hp = 999;
            this.SetTopLeft(_TopLeft);
            LoadContent();
            Sprites = new List<MySprite>();
            Bullets = new List<Bullet>(); 
            Activity = CURRENT_ACTIVITY.STAND;

            Gun MyMiniGun = new MiniGun();
            lstGuns.Add(MyMiniGun);
            Gun MyShotGun = new ShotGun();
            lstGuns.Add(MyShotGun);

            CurrentGun = MyMiniGun;
            
            Facing = RESOURCE_FACE.RIGHT;
            HeightFloor = (int)TopLeft.Y;
            DeltaJump = 0;
        }

        public virtual void LoadContent()
        {
        }

        public virtual void Update(GameTime gameTime, List<Enemy> enemies)
        {
            if (!Isdead)
            {
                if (Hp > 0)
                {
                    UpdateActivity();
                    UpdateBullet(gameTime, enemies);
                    UpdatePosition(gameTime);
                }
                
                MyDisplayer.Update(gameTime);
                Isdead = MyDisplayer.isExtinct();
            }      
        }

        public override void Draw(SpriteBatch spriteBatch)
        {
            if (!Isdead)
            {
                if (Hp > 0)
                {
                    foreach (Bullet bullet in Bullets)
                    {
                        bullet.Draw(spriteBatch);
                    }
                }

                MyDisplayer.Draw(spriteBatch);
            }
            
        }

        public virtual void UpdateBullet(GameTime theGameTime, List<Enemy> enemies)
        {
            foreach (Bullet bullet in Bullets)
            {
                bullet.Update(theGameTime, enemies);
            } 
        }

        public virtual void UpdatePosition(GameTime gameTime)
        {
            Vector2 ufo = TopLeft;

            switch (Activity)
            {
                case CURRENT_ACTIVITY.RUN:
                    if (Facing == RESOURCE_FACE.LEFT)
                    {
                        ufo.X -= CurrentSpeed;
                    }
                    else
                    {
                        ufo.X += CurrentSpeed;
                    }

                    break;
                    
                case CURRENT_ACTIVITY.JUMP:
                    ufo = GetJumpPos(ufo,gameTime);
                    break;
            }

            if(Activity!= CURRENT_ACTIVITY.JUMP && ufo.Y != HeightFloor)
            {
                ufo = GetJumpPos(ufo, gameTime);
            }

            if(ufo.X >= GameUtil.GamePivot.PivotPoint && 
                (ufo.X + Size.X) <= GameUtil.GamePivot.PivotPoint + GameUtil.ScreenSize.X)
            {
                Console.WriteLine("new Pos:" + (Size.X));
                Console.WriteLine("Pivot:"+GameUtil.GamePivot.PivotPoint +"Screen: "+GameUtil.ScreenSize.X);
                SetTopLeft(ufo);
            }
            
        }

        public virtual void ShootFireball()
        {
            if (CurrentGun.TypeOfGun != Guns.Gun.TYPE.MINIGUN)
            {
                while (CurrentGun.CountBullet <= 0)
                {
                    SwitchGun();
                }
            }

            Activity = CURRENT_ACTIVITY.SHOOT;
            List<Bullet> lstFiredBullet = new List<Bullet>();
            lstFiredBullet.AddRange(CurrentGun.Fire(TopLeft, CharDirection));
            Bullets.AddRange(lstFiredBullet);
        }

        public void SwitchGun()
        {
            int indexCurrent = lstGuns.IndexOf(CurrentGun);
            indexCurrent = (indexCurrent + 1) % lstGuns.Count;
            CurrentGun = lstGuns[indexCurrent];
        }


        public virtual void ProcessHotKey()
        {
            if (UserInput.isKeyClicked(Keys.M))
            {
                GameUtil.Audio.IsMuting = !GameUtil.Audio.IsMuting;
            }

            if (UserInput.isKeyClicked(Keys.F2))
            {
                CurrentGun.AddBullet(10);
                if (!GameUtil.Audio.IsMuting)
                {
                    GameUtil.Audio.MenuSelect.Play();
                }
            }

            if (UserInput.isKeyClicked(Keys.F1))
            {
                Hp += 100;
                if (!GameUtil.Audio.IsMuting)
                {
                    GameUtil.Audio.MenuSelect.Play();
                }
            }
        }


        public virtual void UpdateActivity()
        {
            ProcessHotKey();

            Boolean isHaveAPressedKey = false;
            if (Activity != CURRENT_ACTIVITY.JUMP || Activity == CURRENT_ACTIVITY.CROUCH)
            {
                if (UserInput.CurrentKeyBoard.IsKeyDown(Keys.W))
                {
                    Activity = CURRENT_ACTIVITY.UP;
                    CharDirection = new Vector2(0, -1);
                    isHaveAPressedKey = true;
                }
                if (UserInput.CurrentKeyBoard.IsKeyDown(Keys.D))
                {
                    Activity = CURRENT_ACTIVITY.RUN;
                    Facing = RESOURCE_FACE.RIGHT;
                    CharDirection = new Vector2(1, 0);
                    isHaveAPressedKey = true;
                }

                if (UserInput.CurrentKeyBoard.IsKeyDown(Keys.A))
                {
                    Activity = CURRENT_ACTIVITY.RUN;
                    Facing = RESOURCE_FACE.LEFT;
                    CharDirection = new Vector2(-1, 0);
                    isHaveAPressedKey = true;
                }

                if (UserInput.CurrentKeyBoard.IsKeyDown(Keys.K))
                {
                    Activity = CURRENT_ACTIVITY.JUMP;
                    isHaveAPressedKey = true;
                }

                if (UserInput.CurrentKeyBoard.IsKeyDown(Keys.S))
                {
                    Activity = CURRENT_ACTIVITY.CROUCH;
                    isHaveAPressedKey = true;
                }

                if (UserInput.isKeyClicked(Keys.Q))
                {
                    SwitchGun();                
                }
            }
            else
            {
                if (Activity == CURRENT_ACTIVITY.JUMP)
                {
                    if (UserInput.CurrentKeyBoard.IsKeyDown(Keys.D))
                    {
                        Facing = RESOURCE_FACE.RIGHT;
                        isHaveAPressedKey = true;
                    }

                    if (UserInput.CurrentKeyBoard.IsKeyDown(Keys.A))
                    {
                        Facing = RESOURCE_FACE.LEFT;
                        isHaveAPressedKey = true;
                    }
                }

                if (Activity == CURRENT_ACTIVITY.CROUCH)
                {
                    if (UserInput.CurrentKeyBoard.IsKeyDown(Keys.D))
                    {
                        isHaveAPressedKey = true;
                    }
                    if (UserInput.CurrentKeyBoard.IsKeyDown(Keys.A))
                    {
                        isHaveAPressedKey = true;

                    }

                }
            }


            if (UserInput.isKeyClicked(Keys.J))
            {
                SetBulletDirection();
                ShootFireball();
                isHaveAPressedKey = true;
            }

            if (!isHaveAPressedKey && Activity != CURRENT_ACTIVITY.JUMP)
            {
                if (MyDisplayer.isEndShooting())
                {
                    Activity = CURRENT_ACTIVITY.STAND;
                }
                else
                {
                    if (Activity != CURRENT_ACTIVITY.SHOOT)
                    {
                        Activity = CURRENT_ACTIVITY.STAND;
                    }
                }  
            }
        }

        public Vector2 GetJumpPos(Vector2 currentTopLeft, GameTime gameTime)
        {
            Vector2 ufo = currentTopLeft;
            ufo.Y = (DeltaJump - 10) * (DeltaJump - 10) - 150 + HeightFloor;

            if (ufo.X >= 0 && ufo.X < 700)
            {
                ufo.X += CurrentSpeed;
            }

            DeltaJump++;
            if (ufo.Y > HeightFloor)
            {
                ufo.Y = HeightFloor;
                Activity = CURRENT_ACTIVITY.STAND;
                DeltaJump = 0;
            }

            return ufo;
        }


        public virtual void SetBulletDirection()
        {
            switch(Activity)
            {
                case CURRENT_ACTIVITY.UP:
                    CharDirection = -Vector2.UnitY;
                    break;
                
                case CURRENT_ACTIVITY.CROUCH:
                case CURRENT_ACTIVITY.STAND:
                    if (Facing == RESOURCE_FACE.LEFT)
                    {
                        CharDirection = -Vector2.UnitX;
                    }

                    if (Facing == RESOURCE_FACE.RIGHT)
                    {
                        CharDirection = Vector2.UnitX;
                    }
                    break;
            }
        }

        public virtual void SetTopLeft(Vector2 newTopLeft)
        {
            TopLeft = newTopLeft;
            MyDisplayer.SetTopLeft(TopLeft);
        }

        public virtual List<Bullet> GetListBullet()
        {
            return Bullets;
        }

        public virtual List<Gun> GetListGun()
        {
            return lstGuns;
        }

        public void RestoreMemento(IMemento OldMemento)
        {
            HeroMemento MyMemento = (HeroMemento)OldMemento;
            TopLeft = MyMemento.TopLeft;
            Hp = MyMemento.Hp;
            Activity = MyMemento.CurrentActivity;
            Facing = MyMemento.CurrentFacing;

            lstGuns = new List<Gun>();
            foreach (GunMemento gunMemento in MyMemento.GetListGun())
            {
                Gun newGun = GunFactory.GetInstance().GetGun(gunMemento.Type);
                newGun.RestoreMemento(gunMemento);
                lstGuns.Add(newGun);
            }

            CurrentGun = lstGuns.Where(gun => gun.TypeOfGun == MyMemento.CurrentGun).Take(1).SingleOrDefault();
            MyDisplayer.Body.ITexture = MyMemento.IndexBody;
            MyDisplayer.Foot.ITexture = MyMemento.IndexFoot;

        }

        
    }
}
